package com.sc.nft.config;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ReflectUtil;
import com.sc.nft.helper.ElasticsearchHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.nio.entity.NByteArrayEntity;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Elasticsearch 客户端配置，由于当前 SpringBoot 版本问题（最高支持到6.x），故直接使用原生ES客户端
 *
 * @author zlikun
 * @since 2024/06/06
 */
@Slf4j
@Configuration
public class ElasticsearchConfig {

    @Bean(destroyMethod = "close")
    public RestHighLevelClient restHighLevelClient(@Value("${spring.elasticsearch.rest.uris}") String uris,
                                                   @Value("${spring.elasticsearch.rest.username}") String username,
                                                   @Value("${spring.elasticsearch.rest.password}") String password) {

        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));

        RestClientBuilder restClientBuilder = RestClient.builder(HttpHost.create(uris))
                .setHttpClientConfigCallback(builder -> HttpAsyncClients.custom()
                        // 认证配置
                        .setDefaultCredentialsProvider(credentialsProvider)
                        // 请求日志
                        .addInterceptorLast((HttpRequestInterceptor) (request, context) -> {
                            if (!log.isDebugEnabled()) {
                                return;
                            }

                            final StringBuilder sb = new StringBuilder(request.getRequestLine().toString().split("\\?")[0]);

                            // NByteArrayEntity entity = ((HttpRequestWrapper.HttpEntityEnclosingRequestWrapper) request).getEntity();
                            try (NByteArrayEntity entity = ReflectUtil.invoke(request, "getEntity")) {
                                if (entity != null && entity.getContentLength() > 0) {
                                    String body = IoUtil.readUtf8(entity.getContent());
                                    sb.append("\n").append(body);
                                }
                            }

                            log.debug("ES Query >>> \n{}", sb);
                        })
                );

        return new RestHighLevelClient(restClientBuilder);
    }

    @Bean
    @ConditionalOnBean(RestHighLevelClient.class)
    public ElasticsearchHelper elasticsearchHelper() {
        return new ElasticsearchHelper();
    }

}
